﻿using AutoMapper;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using StarsAdmin.Application.Role.Dtos;
using StarsAdmin.Application.User.Dtos;
using StarsAdmin.Core.Cache;
using StarsAdmin.Core.Consts;
using StarsAdmin.Core.DB.Entities;
using StarsAdmin.Core.Exceptions;
using StarsAdmin.Core.Extensions;
using StarsAdmin.Core.Models;
using StarsAdmin.Repository.Menu;
using StarsAdmin.Repository.Role;

namespace StarsAdmin.Application.Role.Services
{
    public class RoleService : IRoleService
    {
        private readonly IMapper _mapper;
        private readonly ICacheService _cache;
        private readonly IRoleRepository _roleRepository;
        private readonly IMenuRepository _menuRepository;
        private readonly IWebHostEnvironment _webHostEnvironment;

        public RoleService(IMapper mapper, ICacheService cacheService, IRoleRepository roleRepository, IMenuRepository menuRepository, IWebHostEnvironment webHostEnvironment)
        {
            _mapper = mapper;
            _cache = cacheService;
            _roleRepository = roleRepository;
            _menuRepository = menuRepository;
            _webHostEnvironment = webHostEnvironment;
        }

        #region 查询

        public async Task<List<RoleDto>> GetAllAsync(BaseQueryInput input)
        {
            var result = await _roleRepository.GetAll().AsNoTracking()
                .WhereIf(input != null && input.QueryConditions.Any(), input.QueryConditions)
                .OrderByIf(input != null && input.Sort != null, input.Sort, input.Order != false)
                .Include(e => e.Menus)
                .ToListAsync();
            return _mapper.Map<List<RoleDto>>(result);
        }

        public async Task<Page<RoleDto>> GetPageAsync(PageQueryInput input)
        {
            var result = await _roleRepository.GetAll().AsNoTracking()
               .WhereIf(input != null && input.QueryConditions.Any(), input.QueryConditions)
               .OrderByIf(input != null && input.Sort != null, input.Sort, input.Order != false)
               .Include(e => e.Menus)
               .ToPageListAsync(input.CurrentPage, input.PageSize);
            return _mapper.Map<Page<RoleDto>>(result);
        }

        public async Task<RoleDto?> GetByIdAsync(long id)
        {
            var result = await _roleRepository.GetById(id).Include(e => e.Menus).FirstOrDefaultAsync();
            return _mapper.Map<RoleDto>(result);
        }

        public async Task<List<RoleDto>> GetByIdsAsync(long[] ids)
        {
            var result = await _roleRepository.GetByIds(ids).ToListAsync();
            return _mapper.Map<List<RoleDto>>(result);
        }

        #endregion 查询

        #region 导入导出

        public async Task<FileContentResult?> ExportTemplateAsync()
        {
            var filePath = "template/角色管理.xlsx";
            var localPath = _webHostEnvironment.WebRootPath.CombineAndFormatPath(filePath);
            // 检查文件是否存在
            if (!System.IO.File.Exists(localPath))
            {
                throw new NotFoundException("未找到指定的模版文件。");
            }
            return await FileExtension.ExportExcelFileAsync(localPath);
        }

        public async Task<FileContentResult?> ExportAsync(long[] ids)
        {
            var export = await _roleRepository.GetByIds(ids).ToListAsync();
            return await _mapper.Map<List<ExportRoleDto>>(export).ToExcelAsync("角色管理");
        }

        public async Task<bool> ImportAsync(List<AddRoleInput> inputs)
        {
            var entities = _mapper.Map<List<RoleEntity>>(inputs);
            var menuIds = inputs.SelectMany(e => e.MenuIds ?? []).ToList();
            if (menuIds != null && menuIds.Count != 0)
            {
                var menus = await _menuRepository.GetByIdsAsync(menuIds);
                if (menus == null || !menus.Any())
                {
                    throw new NotFoundException("未找到指定的菜单权限。");
                }
                foreach (var entity in entities)
                {
                    if (entity.MenuIds != null && entity.MenuIds.Length != 0)
                    {
                        entity.Menus = menus.Where(e => entity.MenuIds.Contains(e.Id)).ToList();
                    }
                }
            }
            var result = await _roleRepository.AddRangeAndSaveAsync(entities);
            if (result)
            {
                await _cache.RemoveAsync(CacheKeyConst.RoleCacheKey);
            }
            return result;
        }

        #endregion 导入导出

        #region 添加

        public async Task<bool> AddAsync(AddRoleInput input)
        {
            var entity = _mapper.Map<RoleEntity>(input);
            if (input.MenuIds != null && input.MenuIds.Length != 0)
            {
                var menus = await _menuRepository.GetByIdsAsync(input.MenuIds);
                if (menus == null || !menus.Any())
                {
                    throw new NotFoundException("未找到指定的菜单权限。");
                }
                entity.Menus = await menus.ToListAsync();
            }
            var result = await _roleRepository.AddAndSaveAsync(entity);
            if (result)
            {
                await _cache.RemoveAsync(CacheKeyConst.RoleCacheKey);
            }
            return result;
        }

        #endregion 添加

        #region 更新

        public async Task<bool> AssignPermissionsAsync(AssignPermissionsInput input)
        {
            var entity = await _roleRepository.GetById(input.Id).Include(e => e.Menus).FirstOrDefaultAsync();
            if (entity == null)
            {
                throw new NotFoundException("未找到指定的角色。");
            }
            var menus = await _menuRepository.GetByIdsAsync(input.Ids);
            if (menus == null || !menus.Any())
            {
                throw new NotFoundException("未找到指定的菜单权限。");
            }
            entity.Menus.Clear();
            entity.Menus = await menus.ToListAsync();
            var result = await _roleRepository.UpdateAndSaveAsync(entity);
            if (result)
            {
                await _cache.RemoveAsync(CacheKeyConst.RoleCacheKey);
            }
            return result;
        }

        public async Task<bool> UpdateAsync(UpdateRoleInput input)
        {
            var role = await _roleRepository.GetById(input.Id).Include(e => e.Menus).FirstOrDefaultAsync();
            if (role == null)
            {
                throw new NotFoundException("未找到指定的角色。");
            }
            var entity = _mapper.Map(input, role);
            if (input.MenuIds != null && input.MenuIds.Length != 0)
            {
                var menus = await _menuRepository.GetByIdsAsync(input.MenuIds);
                if (menus == null || !menus.Any())
                {
                    throw new NotFoundException("未找到指定的菜单权限。");
                }
                entity.Menus.Clear();
                entity.Menus = await menus.ToListAsync();
            }
            var result = await _roleRepository.UpdateAndSaveAsync(entity);
            if (result)
            {
                await _cache.RemoveAsync(CacheKeyConst.RoleCacheKey);
            }
            return result;
        }

        public async Task<bool> EnabledAsync(long id)
        {
            var entity = await _roleRepository.GetByIdAsync(id);
            if (entity == null)
            {
                throw new NotFoundException("未找到指定的角色。");
            }
            entity.IsEnabled = !entity.IsEnabled;
            var result = await _roleRepository.UpdateAndSaveAsync(entity);
            if (result)
            {
                await _cache.RemoveAsync(CacheKeyConst.RoleCacheKey);
            }
            return result;
        }

        #endregion 更新

        #region 删除

        public async Task<bool> DeleteAsync(long id)
        {
            var entity = await _roleRepository.GetById(id).Include(e => e.Users).Include(e => e.Menus).FirstOrDefaultAsync();
            if (entity == null)
            {
                throw new NotFoundException("未找到指定的角色。");
            }
            if (entity.Users.Count > 0)
            {
                throw new InUseException($"{entity.Name}角色已经分配给用户，无法删除。");
            }
            var result = await _roleRepository.DeleteAsync(entity.Id);
            if (result)
            {
                entity.Menus.Clear();
                await _roleRepository.SaveChangesAsync();
                await _cache.RemoveAsync(CacheKeyConst.RoleCacheKey);
            }
            return result;
        }

        public async Task<bool> BatchDeleteAsync(long[] ids)
        {
            var entities = await _roleRepository.GetByIds(ids).Include(e => e.Users).Include(e => e.Menus).ToListAsync();
            if (entities == null || entities.Count < 1)
            {
                throw new NotFoundException("未找到指定的角色。");
            }
            _ = entities.Any(e =>
            {
                if (e.Users.Count > 0)
                {
                    throw new InUseException($"{e.Name}角色已经分配给用户，无法删除。");
                }
                return true;
            });
            var result = await _roleRepository.DeleteRangeAsync(ids);
            if (result)
            {
                foreach (var entity in entities)
                {
                    entity?.Menus.Clear();
                }
                await _roleRepository.SaveChangesAsync();
                await _cache.RemoveAsync(CacheKeyConst.RoleCacheKey);
            }
            return result;
        }

        #endregion 删除
    }
}